#include <iostream>
#include <cassert>
#include <signal.h>
#include <unistd.h>

using namespace std;

static void showPending(const sigset_t&);

static void handler(int signo)
{
  cout << "执行 " << signo << " 号信号" << endl;

  //退出前，打印 pending 表
  sigset_t pending;
  sigemptyset(&pending);
  showPending(pending);
  //exit(1);
}

static void showPending(const sigset_t& pending)
{
  cout << "当前进程 " << getpid() << " 的 pending 表为：";

  for(int i = 1; i <= 31; i++)
  {
    if(sigismember(&pending, i)) cout << 1;
    else cout << 0;
  }
  cout << endl;
}

int main()
{
  //改变2号信号的动作
  signal(SIGINT, handler);

  //改变40号信号的动作
  signal(SIGRTMIN+6, handler);


  //1、创建信号集存放 block 表
  sigset_t set, oset;
  sigemptyset(&set);  //初始化
  sigemptyset(&oset);

  //2、将待屏蔽的信号添加至信号集中
  sigaddset(&set, SIGINT);
  sigaddset(&set, SIGRTMIN+6);

  //3、屏蔽目标信号，并将原来的 block 表存入 oset 信号集中
  sigprocmask(SIG_BLOCK, &set, &oset);

  //4、循环，等待信号
  int cnt = 10;
  while(true)
  {
    sigset_t pending; //未决表
    sigemptyset(&pending);  //初始化
    int n = sigpending(&pending); //获取未决表
    assert(n == 0);
    (void)n;

    showPending(pending); //打印未决表信息
    sleep(1);

    //10 秒后取消 block 状态，信号立即递达(执行相关动作)
    if(cnt-- == 0)
    {
      //sigprocmask(SIG_UNBLOCK, &set, nullptr); //方式一，通过 SIG_BLOCK 取消指定信号的阻塞
      sigprocmask(SIG_SETMASK, &oset, nullptr); //方式二，通过原来的 block 表，取消阻塞
    }
  }

  return 0;
}
